package com.example.springbooteasycode.bootsocket;

import org.springframework.stereotype.Component;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ThreadLocalRandom;

@Component // 被 Spring 管理
public class SocketServer {
    // 服务端监听端口（可配置在 application.yml 中）
    private static final int SERVER_PORT = 8888;
    // 用 ThreadLocal 保存当前请求的客户端端口（供 AOP 切面获取）
    private static final ThreadLocal<Integer> clientPortHolder = new ThreadLocal<>();

    // 启动 Socket 服务端（由 Spring 启动时调用）
    public void start() {
        new Thread(() -> { // 独立线程运行，避免阻塞 Spring 启动
            try (ServerSocket serverSocket = new ServerSocket(SERVER_PORT)) {
                System.out.println("Socket 服务端已启动，监听端口：" + SERVER_PORT);
                while (!Thread.currentThread().isInterrupted()) {
                    // 接受客户端连接（阻塞方法）
                    Socket clientSocket = serverSocket.accept();
                    // 保存客户端端口到 ThreadLocal (这个是动态的，不是要想要的。)
                    int clientPort = clientSocket.getPort();
                    clientPortHolder.set(clientPort);
                    System.out.println("新客户端连接，端口：" + clientPort);

                    // 处理客户端请求（交给解析器）
                    handleClient(clientSocket);
                }
            } catch (IOException e) {
                System.err.println("Socket 服务端异常：" + e.getMessage());
            }
        }).start();
    }

    // 处理客户端请求，调用 parseCommand 方法
    private void handleClient(Socket clientSocket) {
        try {
            // 获取 Spring 容器中的解析器（确保被 Spring 管理）
            KoalCommandParser parser = SpringContextHolder.getBean(KoalCommandParser.class);
            // 从客户端输入流读取数据（简化示例，实际需根据协议解析）
            byte[] requestData = new byte[1024];
            int len = clientSocket.getInputStream().read(requestData);
            byte[] validData = new byte[len];
            System.arraycopy(requestData, 0, validData, 0, len);

            // 调用带 @LogA 注解的 parseCommand 方法（触发 AOP 切面）
            byte[] response = parser.parseCommand(validData);
            // 调用带 @LogB 注解的 parseEncryptionCommand 方法（触发 AOP 切面）
//            byte[] response = parser.parseEncryptionCommand(validData);

            // 向客户端写入响应
            clientSocket.getOutputStream().write(response);
            clientSocket.getOutputStream().flush();
        } catch (IOException e) {
            System.err.println("客户端处理异常：" + e.getMessage());
        } finally {
            // 清理 ThreadLocal（避免内存泄漏）
            clientPortHolder.remove();
            try {
                clientSocket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    // 供 AOP 切面获取客户端端口
    public static Integer getClientPort() {
        return clientPortHolder.get();
    }

    // 供 AOP 切面获取服务端端口
    public static Integer getServerPort() {
        return SERVER_PORT;
    }
}
